/****************************************************************************
copyright (c) 2020 
-----------------------------------------------------------------------------
           http_server.h

Module Name: 
Date Created: 2020/09/11
Author: hthappiness
Description: xxxxxxxxxxxxxxxxxxxxx
****************************************************************************/

#pragma once

#include <functional>
#include <memory>
#include <map>
#include <string>

#include "boost/asio/io_context.hpp"
#include "boost/asio/thread_pool.hpp"

#include "boost/asio/ip/tcp.hpp"
#include "boost/beast/http.hpp"

namespace Doraemon
{
    class HttpRequest;
    class HttpSession;

    namespace http
    {
        using httpRequestHandler = std::function<int(HttpRequest&, std::string&)>;

        class HttpListener : public std::enable_shared_from_this<HttpListener>
        {
        public:
            int run(boost::asio::ip::tcp::endpoint& endpoint);
        private:
            void do_accept();
            void on_accept(boost::beast::error_code err, boost::asio::ip::tcp::socket socket);
        private:
            boost::asio::ip::tcp::acceptor m_acceptor;
            boost::asio::ip::tcp::socket m_socket;

            boost::asio::io_context& m_ctx;
        };

        class HttpServer : public std::enable_shared_from_this<HttpServer>
        {

        public:

            class HttpRoutePath
            {
                using RouteHandler = std::function<int (std::shared_ptr<HttpSession>, HttpRequest&)>;
            public:

            private:
                std::map<std::string, RouteHandler> m_putRouteMap;
                std::map<std::string, RouteHandler> m_getRouteMap;
                std::map<std::string, RouteHandler> m_postRouteMap;
                std::map<std::string, RouteHandler> m_deleteRouteMap;
            };

        private:

            boost::asio::io_context m_ctx;
            boost::asio::thread_pool m_pool;

            HttpRoutePath m_routePath;

            std::shared_ptr<HttpListener> m_spListener;
        };
    };
}